/**
 * eclipse 
 */
package com.atlassian.jira.user.osuser;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.Properties;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.opensaml.Configuration;
import org.opensaml.DefaultBootstrap;
import org.opensaml.saml2.core.Response;
import org.opensaml.xml.ConfigurationException;
import org.opensaml.xml.io.Unmarshaller;
import org.opensaml.xml.io.UnmarshallerFactory;
import org.opensaml.xml.io.UnmarshallingException;
import org.opensaml.xml.signature.SignatureValidator;
import org.opensaml.xml.validation.ValidationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

/**
 * @author suresh This class extends the default JIRA credentials provider
 *         (JiraOFBizCredentialsProvider).
 * 
 */
public class JiraSaml2CredentialProvider extends JiraOFBizCredentialsProvider {

	private static final long serialVersionUID = 1L;
	private static boolean bootStrapped = false;

	// handles authentication if a SAML token received else pass to super
	@Override
	public boolean authenticate(String userName, String passWord) {
		boolean isValidated = false;
		isValidated = super.authenticate(userName, passWord);
		System.out.println("super authenticater: " + isValidated);
		if (isValidated == false) {
			try {
				isValidated = this.validateToken(userName);
			} catch (ParserConfigurationException e) {
				e.printStackTrace();
				return false;
			} catch (SAXException e) {
				e.printStackTrace();
				return false;
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			} catch (UnmarshallingException e) {
				e.printStackTrace();
				return false;
			} catch (ConfigurationException e) {
				e.printStackTrace();
				return false;
			} catch (CertificateException e) {
				e.printStackTrace();
				return false;
			} catch (ValidationException e) {
				e.printStackTrace();
				return false;
			}
		}
		return isValidated;
	}

	// validates saml2 tokens
	private boolean validateToken(String samlToken)
			throws ParserConfigurationException, SAXException, IOException,
			UnmarshallingException, ConfigurationException,
			CertificateException, ValidationException {
		// get the original response from the token
		Response response = this.unmarshall(samlToken);
		// pass the original response message for validation
		boolean isValidated = this.validateSignature(response);
		return isValidated;
	}

	// converts the string saml token to a SAML Response object
	private Response unmarshall(String authReqStr)
			throws ParserConfigurationException, SAXException, IOException,
			UnmarshallingException, ConfigurationException {

		doBootstrap();
		DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
				.newInstance();
		documentBuilderFactory.setNamespaceAware(true);
		DocumentBuilder docBuilder = documentBuilderFactory
				.newDocumentBuilder();
		Document document = docBuilder.parse(new ByteArrayInputStream(
				authReqStr.trim().getBytes()));
		Element element = document.getDocumentElement();
		UnmarshallerFactory unmarshallerFactory = Configuration
				.getUnmarshallerFactory();
		Unmarshaller unmarshaller = unmarshallerFactory
				.getUnmarshaller(element);
		return (Response) unmarshaller.unmarshall(element);

	}

	private void doBootstrap() throws ConfigurationException {
		if (!bootStrapped) {
			DefaultBootstrap.bootstrap();
			bootStrapped = true;
		}
	}

	// validates the signature of the response message
	admin

	// invokes the super handles() method
	@Override
	public boolean handles(String arg0) {
		boolean isHandled = super.handles(arg0);
		return isHandled;
	}

	// invokes the super init() method
	@Override
	public boolean init(Properties properties) {
		boolean isInit = super.init(properties);
		// String url = properties.getProperty("identity-provider-url");
		return isInit;
	}

}
